#ifndef TRANSFERSOCKET_H
#define TRANSFERSOCKET_H
/*!
 ***********************************************************************************
 * @File      : transfersocket.h
 * @Brief     : 简要说明
 * @Details   : 详细说明
 * @Author    : BinWatson
 * @Date      : 2022-05-27 10:50:13
 * @Version   : v1.0
 * @Copyright : Copyright By BinWatson, All Rights Reserved
 ***********************************************************************************/

#include "TcpManager_global.h"
#include <QObject>
#include <QTcpSocket>
#include <QIODevice>
#include <QQueue>
#include <QFile>

#include "tcpblock.h"
#include "CallBacks.h"


class TcpManager;
class TransferSocketPrivate;

class TRANFERSOCKET_EXPORT TransferSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TransferSocket(QObject *parent = nullptr, TcpManager* manager = nullptr);
    ~TransferSocket();

public slots:

    /**
     * @brief   : 设置套接字名字，与设置objectName等价，线程安全
     * @param   : name description
     * @return  : 返回值说明
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-05-27 10:14:49
     */
    Q_INVOKABLE void setSocketName(const QString& name);
    // 与objectName()等价
    Q_INVOKABLE QString socketName() const;

    /**
     * @brief   : 设置进度条间隔，线程安全
     * @param   : miscellaneous 毫秒级
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-06-20 21:49:54
     */
    Q_INVOKABLE void setBarInterval(const qint64 miscellaneous);
    Q_INVOKABLE qint64 barInterval() const { return m_barInterval; }

public:
    /**
     * @brief   : Asynchronous的方式写入套接字，会立即返回，该函数是不可重入的。
     * @param   : file 要发送的文件对象
     * @author  : BinWatson
     * @version : v1.3
     * @date    : 2022-06-20 21:54:37
     * @details : 发送期间每个barInterval时间就会触发一次writingBar信号，
     *            用于告知当前发送的进度
     */
    Q_INVOKABLE void sendFile(QSharedPointer<QFile> file);

    /**
     * @brief   : Synchronous的方式写入套接字。
     * @param   : message 二进制流数据
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-06-20 21:54:37
     * @details : 该函数特定用于RenderEngine
     */
    Q_INVOKABLE void sendFigure(QByteArray message);

    /**
     * @brief   : Asynchronous的方式断开套接字连接
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-06-20 21:56:30
     * @details : 成功断开后会触发disconnected信号。
     */

    Q_INVOKABLE void disconnectFromHost();

    void setNewTcpBlockCallBack(const NewTcpBlockCallBack& callback);

signals:

    /**
     * @brief   : 文件发送结束后会触发该信号
     * @param   : file 文件的智能指针
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-06-24 11:12:08
     */
    void sendFileComplete(QSharedPointer<QFile> file);

    /**
     * @brief   : 发送进度条，时间间隔通过setBarInterval()进行设置。
     * @param   : file 正在发送的文件
     * @param   : magic 该文件的唯一标识符
     * @param   : offset 当前正在发送的文件偏移量
     * @return  : 返回值说明
     * @author  : BinWatson
     * @version : v1.0
     * @date    : 2022-06-24 11:13:36
     * @details : 详细说明
     */
    void writingFileBar(QSharedPointer<QFile> file, qint64 magic, qint64 offset);

public slots:
    void onMessage();           /* 套接字可读时被调用 */

    /**
     * @brief   : 同步的方式写入，当数据发送完毕后会返回。
     * @param   : data 需要发送的数据
     * @author  : BinWatson
     * @version : v1.5
     * @date    : 2022-06-24 11:15:33
     * @details : 写入成功后会发送bytesWritten信号由，父类IODevice产生。
     */
    void writeToSocket(QByteArray data);

private:
    bool runInLoop() const;

private:
    int m_maxTaskNum;
    TransferSocketPrivate *d;
    QString m_cachePath;    /* 暂时存储文件中 */
    qint64 m_barInterval;   /* 默认值为1s */
    TcpManager *m_manager;
    NewTcpBlockCallBack m_newTcpBlockCallBack;
};

#endif // TRANSFERSOCKET_H
